﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using Jive.CustomControls;
using Jive.Helpers;
using JmShared;
using Jive.Models;
using Jive.Network;
using Jive.Settings;
using Jive.User;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace Jive.ViewModels
{
    public class ViewModelPrivateMessagePage : ViewModelBase
    {
        private object LockObject = new object();
        private DateTime LastMessageReceivedTime { get; set; }
        public RelayCommand<SendMessageEventArgs> SendMessageCommand { get; private set; }
        public ObservableCollection<MessageModel> Messages { get; set; }
        public ObservableCollection<EmoticonModel> CustomEmoticons { get; set; }
        public ObservableCollection<EmoticonModel> DefaultEmoticons { get; set; }
        public ObservableCollection<EmoticonModel> RecentlyUsedEmoticons { get; set; }
        public UserInfo PmTarget { get; set; }
        public RelayCommand<EmoticonClickedEventArgs> EmoticonPopupClickEmoticonCommand { get; private set; }
        public RelayCommand<string> EmoticonPopupSendMessageCommand { get; private set; }
        public RelayCommand EmoticonPopupBackspaceCommand { get; private set; }
        public RelayCommand<System.Windows.Input.GestureEventArgs> ChatControlWindowTappedCommand { get; private set; }
        public RelayCommand ShowFauxKeyboardCompletedCommand { get; private set; }
        public RelayCommand HideFauxKeyboardCompletedCommand { get; private set; }
        public RelayCommand AppBarEmoticonsCommand { get; private set; }


        //private ObservableCollection<EmoticonModel> _customEmoticons;
        //public ObservableCollection<EmoticonModel> CustomEmoticons
        //{
        //    get { return _customEmoticons; }
        //    set
        //    {
        //        if (_customEmoticons != value)
        //        {
        //            _customEmoticons = value;
        //            RaisePropertyChanged("CustomEmoticons");
        //        }
        //    }
        //}


        //private ObservableCollection<EmoticonModel> _defaultEmoticon;
        //public ObservableCollection<EmoticonModel> DefaultEmoticons
        //{
        //    get { return _defaultEmoticon; }
        //    set
        //    {
        //        if (_defaultEmoticon != value)
        //        {
        //            _defaultEmoticon = value;
        //            RaisePropertyChanged("DefaultEmoticons");
        //        }
        //    }
        //}

        //private ObservableCollection<EmoticonModel> _recentlyUsedEmoticons;
        //public ObservableCollection<EmoticonModel> RecentlyUsedEmoticons
        //{
        //    get { return _recentlyUsedEmoticons; }
        //    set
        //    {
        //        if (_recentlyUsedEmoticons != value)
        //        {
        //            _recentlyUsedEmoticons = value;
        //            RaisePropertyChanged("RecentlyUsedEmoticons");
        //        }
        //    }
        //}

        private Color _appBarForegroundColor;

        public Color AppBarForegroundColor
        {
            get { return _appBarForegroundColor; }
            set
            {
                if (_appBarForegroundColor != value)
                {
                    _appBarForegroundColor = value;
                    RaisePropertyChanged("AppBarForegroundColor");
                }
            }
        }

        private int _inputTextSelectionLength;
        public int InputTextSelectionLength
        {
            get { return _inputTextSelectionLength; }
            set
            {
                if (_inputTextSelectionLength != value)
                {
                    _inputTextSelectionLength = value;
                    RaisePropertyChanged("InputTextSelectionLength");
                }
            }
        }


        private int _intputTextSelectionStart;
        public int InputTextSelectionStart
        {
            get { return _intputTextSelectionStart; }
            set
            {
                if (_intputTextSelectionStart != value)
                {
                    _intputTextSelectionStart = value;
                    RaisePropertyChanged("InputTextSelectionStart");
                }
            }
        }

        private string _inputText;
        public string InputText
        {
            get { return _inputText; }
            set
            {
                if (_inputText != value)
                {
                    _inputText = value;
                    RaisePropertyChanged("InputText");
                }
            }
        }

        private string _pmTargetDisplayName;

        public string PmTargetDisplayName
        {
            get { return _pmTargetDisplayName; }
            set
            {
                if (value != _pmTargetDisplayName)
                {
                    _pmTargetDisplayName = value;
                    RaisePropertyChanged("PmTargetDisplayName");
                }
            }
        }

        private bool _showKeyboard;

        public bool ShowKeyboard
        {
            get { return _showKeyboard; }
            set
            {
                if (_showKeyboard != value)
                {
                    _showKeyboard = value;
                    if (value == true)
                    {
                        ShowEmoticonPopup = false;
                    }
                    if (!ShowEmoticonPopup)
                        ShowFauxKeyboardGrid = value;

                    RaisePropertyChanged("ShowKeyboard");
                }
            }
        }

        private bool _showFauxKeyboardGrid;

        public bool ShowFauxKeyboardGrid
        {
            get { return _showFauxKeyboardGrid; }
            set
            {
                if (_showFauxKeyboardGrid != value)
                {
                    _showFauxKeyboardGrid = value;
                    RaisePropertyChanged("ShowFauxKeyboardGrid");
                }
            }
        }
        private Uri _emoticonButtonIconUri;

        public Uri EmoticonButtonIconUri
        {
            get { return _emoticonButtonIconUri; }
            set
            {
                if (value != this._emoticonButtonIconUri)
                {
                    this._emoticonButtonIconUri = value;
                    RaisePropertyChanged("EmoticonButtonIconUri");
                }
            }
        }

        private string _emoticonButtonDisplayText;

        public string EmoticonButtonDisplayText
        {
            get { return _emoticonButtonDisplayText; }
            set
            {
                if (_emoticonButtonDisplayText != value)
                {
                    _emoticonButtonDisplayText = value;
                    RaisePropertyChanged("EmoticonButtonDisplayText");
                }
            }
        }
        private bool _showEmoticonPopup;

        public bool ShowEmoticonPopup
        {
            get { return _showEmoticonPopup; }
            set
            {


                if (_showEmoticonPopup != value)
                {
                    _showEmoticonPopup = value;
                    if (value == true)
                    {
                        ShowKeyboard = false;
                        EmoticonButtonDisplayText = "Keyboard";
                        EmoticonButtonIconUri = new Uri("/Assets/AppBar/appbar.input.keyboard.png", UriKind.Relative);
                    }
                    else
                    {
                        EmoticonButtonDisplayText = "Emoticons";
                        EmoticonButtonIconUri = new Uri("/Assets/AppBar/appbar.smiley.happy.png", UriKind.Relative);
                    }
                    if (!ShowKeyboard)
                        ShowFauxKeyboardGrid = value;


                    RaisePropertyChanged("ShowEmoticonPopup");
                }
            }
        }
        private int _remainingMessages;

        public int RemainingMessages
        {
            get { return _remainingMessages; }
            set
            {
                if (value != this._remainingMessages)
                {
                    this._remainingMessages = value;
                    RaisePropertyChanged("RemainingMessages");
                    RaisePropertyChanged("ShowChatControl");
                    RaisePropertyChanged("ShowLoadAnimation");
                }
            }
        }
        public ViewModelPrivateMessagePage()
        {

            if (DesignerProperties.IsInDesignTool)
                return;

            AppBarForegroundColor = Colors.Green;

            DefaultEmoticons = CreateDefaultEmoticonList();
            CustomEmoticons = CreateCustomEmoticonList();
            InputText = string.Empty;
            UpdateRecentlyUsedEmoticonList();
            ChatControlWindowTappedCommand = new RelayCommand<System.Windows.Input.GestureEventArgs>(ChatControlWindowTappedCommandAction);
            EmoticonPopupBackspaceCommand = new RelayCommand(EmoticonPopupBackspaceCommandAction);
            EmoticonPopupClickEmoticonCommand = new RelayCommand<EmoticonClickedEventArgs>(EmoticonPopupClickEmoticonCommandAction);
            EmoticonPopupSendMessageCommand = new RelayCommand<string>(EmoticonPopupSendMessageCommandAction);
            ShowFauxKeyboardCompletedCommand = new RelayCommand(ShowFauxKeyboardCompletedCommandAction);
            HideFauxKeyboardCompletedCommand = new RelayCommand(HideFauxKeyboardCompletedCommandAction);
            SendMessageCommand = new RelayCommand<SendMessageEventArgs>(SendMessageCommandAction);
            AppBarEmoticonsCommand = new RelayCommand(AppBarEmoticonsAction);
        }

        public override void Cleanup()
        {

            this.PmTarget = null;
            this.Messages = null;
            PmTargetDisplayName = string.Empty;
            base.Cleanup();
        }
        private void UpdateRecentlyUsedEmoticonList(EmoticonModel model = null)
        {
            if (model == null)
            {
                if (RecentlyUsedEmoticons == null)
                    RecentlyUsedEmoticons = new ObservableCollection<EmoticonModel>();
                foreach (var v in AppSettings.AppSettingsInstance.RecentlyUsedCustomEmoticons)
                {
                    model = CustomEmoticons.FirstOrDefault(x => (string)x.EmoticonShortcut == v.Key);
                    if (!RecentlyUsedEmoticons.Contains(model))
                        RecentlyUsedEmoticons.Add(model);
                }
                foreach (var v in AppSettings.AppSettingsInstance.RecentlyUsedDefaultEmoticons)
                {
                    model = DefaultEmoticons.FirstOrDefault(x => ((string[])x.EmoticonShortcut).SequenceEqual(v.Key));
                    if (!RecentlyUsedEmoticons.Contains(model))
                        RecentlyUsedEmoticons.Add(model);
                }
            }
            else
            {
                if (!RecentlyUsedEmoticons.Contains(model))
                    RecentlyUsedEmoticons.Add(model);
            }
            if (RecentlyUsedEmoticons == null)
                return;
            var sortedList = RecentlyUsedEmoticons.ToList();
            sortedList.Sort((x, y) =>
            {
                int thisCount = 0;
                if (x.EmoticonType == EmoticonType.CustomEmoticon)
                    thisCount = AppSettings.AppSettingsInstance.RecentlyUsedCustomEmoticons[(string)x.EmoticonShortcut];
                else if (x.EmoticonType == EmoticonType.DefaultEmoticon)
                {
                    var key = (string[])x.EmoticonShortcut;
                    thisCount = AppSettings.AppSettingsInstance.RecentlyUsedDefaultEmoticons.Where(z => z.Key.SequenceEqual(key)).First().Value;
                }

                int otherCount = 0;

                if (y.EmoticonType == EmoticonType.DefaultEmoticon)
                {
                    var key = (string[])y.EmoticonShortcut;
                    otherCount = AppSettings.AppSettingsInstance.RecentlyUsedDefaultEmoticons.Where(z => z.Key.SequenceEqual(key)).First().Value;
                }
                else if (y.EmoticonType == EmoticonType.CustomEmoticon)
                    otherCount = AppSettings.AppSettingsInstance.RecentlyUsedCustomEmoticons[(string)y.EmoticonShortcut];

                if (thisCount > otherCount)
                    return 0;
                else
                    return 1;

            });
            RecentlyUsedEmoticons = new ObservableCollection<EmoticonModel>(sortedList);
        }
        public void RunOnNetworkDisconnect()
        {
            Deployment.Current.Dispatcher.BeginInvoke(() => this.AppBarForegroundColor = StaticSettings.MaroonColor);
        }

        public void LoadUser(string userName)
        {
            if (Client.ClientInstance.CurrentUserInfo.UserName == userName)
                this.PmTarget = Client.ClientInstance.CurrentUserInfo;
            else
                this.PmTarget = Client.ClientInstance.ConnectedClients.Values.FirstOrDefault(x => x.UserName == userName);
            IEnumerable<MessageModel> messages = from v in Client.ClientInstance.PrivateMessages[userName]
                                                 select CreateMessageModel(v);
            this.Messages = new System.Collections.ObjectModel.ObservableCollection<MessageModel>(messages);
            PmTargetDisplayName = PmTarget.PrettyName;
        }

        private MessageModel CreateMessageModel(ChatMessage msg)
        {
            UserInfo user = (msg.SenderID == Client.ClientInstance.CurrentUserInfo.UserID) ? Client.ClientInstance.CurrentUserInfo : Client.ClientInstance.ConnectedClients[msg.SenderID];
            return CreateMessageModel(user, msg.Message, msg.MessageRelayTime);
        }
        private MessageModel CreateMessageModel(UserInfo user, string message, DateTime messageRelayTime)
        {
            bool showSender = !(user.UserName == "GreenText" || user.UserName == "RedText");
            FontStyle style;
            FontWeight weight;
            StaticMethods.ParseFontStyle(user.FontStyle, out style, out weight);

            return new MessageModel(user.UserID, messageRelayTime)
            {
                NickName = user.PrettyName,
                IsUserNameVisible = showSender,
                MessageText = message,
                FontWeight = weight,
                FontStyle = style,
                FontColor = new SolidColorBrush(StaticMethods.ColorFromHex(user.Color)),
            };
        }
        private void ChatControlWindowTappedCommandAction(System.Windows.Input.GestureEventArgs obj)
        {
            this.ShowEmoticonPopup = false;

            ShowKeyboard = false;
        }

        private void SendMessageCommandAction(SendMessageEventArgs args)
        {
            SendMessage(args.Text);
        }

        private ObservableCollection<EmoticonModel> CreateDefaultEmoticonList()
        {
            ObservableCollection<EmoticonModel> list = new ObservableCollection<EmoticonModel>();
            foreach (KeyValuePair<string[], string> kvp in StaticSettings.DefaultEmoticons)
            {
                list.Add(new EmoticonModel() { EmoticonShortcut = kvp.Key, EmoticonType = EmoticonType.DefaultEmoticon, EmoticonPath = "/Assets/DefaultEmoticons/" + kvp.Value });
            }
            return list;
        }


        public ObservableCollection<EmoticonModel> CreateCustomEmoticonList()
        {
            ObservableCollection<EmoticonModel> list = new ObservableCollection<EmoticonModel>();
            foreach (KeyValuePair<string, string> kvp in StaticSettings.CustomEmoticons)
            {
                list.Add(new EmoticonModel() { EmoticonShortcut = kvp.Key, EmoticonType = EmoticonType.CustomEmoticon, EmoticonPath = kvp.Value });
            }
            return list;
        }
        private void AppBarEmoticonsAction()
        {

            if (ShowEmoticonPopup)
            {
                ShowEmoticonPopup = false;
                ShowKeyboard = true;
                return;
            }

            ShowEmoticonPopup = true;
        }
        public bool ShowChatControl
        {
            get
            {
                return RemainingMessages == 0;
            }
        }
        public bool ShowLoadAnimation
        {
            get
            {
                return RemainingMessages > 0;
            }
        }
        private void ShowFauxKeyboardCompletedCommandAction()
        {

        }
        private void HideFauxKeyboardCompletedCommandAction()
        {

        }

        private void EmoticonPopupBackspaceCommandAction()
        {

            int index = this.InputTextSelectionStart - 1;
            if (index > 0)
            {
                this.InputText = InputText.Remove(index, 1);
                this.InputTextSelectionStart = index;
                this.InputTextSelectionLength = 0;
            }
            else
                this.InputText = string.Empty;
        }

        private void EmoticonPopupClickEmoticonCommandAction(EmoticonClickedEventArgs args)
        {
            EmoticonModel model = args.Model;
            string key = string.Empty;

            if (model.EmoticonType == EmoticonType.CustomEmoticon)
            {
                key = model.EmoticonShortcut.ToString();
                if (!AppSettings.AppSettingsInstance.RecentlyUsedCustomEmoticons.ContainsKey(key))
                    AppSettings.AppSettingsInstance.RecentlyUsedCustomEmoticons.Add(key, 0);
                AppSettings.AppSettingsInstance.RecentlyUsedCustomEmoticons[key]++;
            }
            else if (model.EmoticonType == EmoticonType.DefaultEmoticon)
            {
                string[] keyArray = model.EmoticonShortcut as string[];
                key = keyArray[0];
                if (!AppSettings.AppSettingsInstance.RecentlyUsedDefaultEmoticons.ContainsKey(keyArray))
                    AppSettings.AppSettingsInstance.RecentlyUsedDefaultEmoticons.Add(keyArray, 0);
                AppSettings.AppSettingsInstance.RecentlyUsedDefaultEmoticons[keyArray]++;

            }
            UpdateRecentlyUsedEmoticonList(model);
            InsertEmoticon(key);
        }
        private void InsertEmoticon(string key)
        {
            int offset = InputTextSelectionStart;
            InputTextSelectionLength = 0;
            InputText = InputText.Insert(offset, key);
            InputTextSelectionStart = offset + key.Length;
        }
        private void EmoticonPopupSendMessageCommandAction(string messageText)
        {
            SendMessage(messageText);
            this.InputText = string.Empty;
            ShowEmoticonPopup = false;
            ShowKeyboard = true;

        }

        public void SendMessage(string text)
        {
            if (Client.ClientInstance.IsLoggedIn)
            {
                UserInfo info = this.PmTarget;
                MessageType mt = MessageType.PM;
                string[] targets = info != null ? new string[1] { info.UserID } : null;
                if (targets == null)
                {
                    AddMessage(Client.RedText, "Error occured, recepient not found", MessageType.Error, DateTime.Now);
                    return;
                }

                AddMessage(Client.ClientInstance.CurrentUserInfo, text, mt, DateTime.Now);
                ChatMessage msg = new ChatMessage()
                {
                    Message = text,
                    MessageType = mt,
                    Recipients = targets,
                    SenderID = Client.ClientInstance.CurrentUserInfo.UserID,
                    MessageRelayTime = DateTime.Now
                };

                if (!App.Connection.SendMessage(msg))
                {
                    AddMessage(Client.RedText, String.Format("Could not deliver message: \r\n{0}", msg.Message), MessageType.Error, DateTime.Now);
                }
                else
                    Client.ClientInstance.PrivateMessages[info.UserName].Add(msg);
            }
            else
            {
                Messenger.Default.Send("Not logged in");
            }
        }
        public void AddMessage(UserInfo user, string message, MessageType mt, DateTime timestamp, bool doScroll = true)
        {
            if (user == null)
                throw new InvalidOperationException("UserInfo is null");
            if (String.IsNullOrEmpty(message))
                return;
            if (user.Color == null)
                user.Color = "#000000";

            bool forceToEnd = user.Equals(Client.ClientInstance.CurrentUserInfo);


            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                lock (LockObject)
                {
                    MessageModel lastMsg = this.Messages.Count > 0 ? this.Messages.Last() : null;
                    if (lastMsg != null && timestamp.Subtract(LastMessageReceivedTime).TotalSeconds < 10 && lastMsg.UserID == user.UserID)
                    {
                        lastMsg.MessageText += Environment.NewLine + message;
                    }
                    else
                    {
                        this.Messages.Add(CreateMessageModel(user, message, timestamp));
                    }

                    LastMessageReceivedTime = timestamp;
                }
            });
        }
    }
}
